#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 导入必要的库
import RPi.GPIO as GPIO  # RPi.GPIO 用于控制树莓派的GPIO引脚
import time              # 导入时间库 

# 设置GPIO编号模式为BCM编码方案
GPIO.setmode(GPIO.BCM)
# 定义使用的PWM输出引脚（BCM编号21号引脚）
PWM = 21
# 设置PWM信号频率为40Hz
FREQUENCY = 40
# 设置占空比为0.4（每个周期内高电平时间占比40%）
DUTY = 0.4
# 初始化指定引脚为输出模式
GPIO.setup(PWM, GPIO.OUT)

# don't use too large freq
# 计算PWM信号高电平和低电平持续时间
#   freq - PWM信号频率 duty - 占空比（0.0-1.0）
def calc_delay_period(freq, duty):
    t = 1.0/freq  # 计算单个周期总时长
    ph = t*duty   # 计算高电平阶段时长
    pl = t - ph   # 计算低电平阶段时长
    return ph, pl # ph - 高电平持续时间（秒）pl - 低电平持续时间（秒）

# 通过当前设置的频率和占空比计算持续时间
period_h, period_l = calc_delay_period(FREQUENCY, DUTY)

try:
    # 主循环持续生成PWM信号，实现软件PWM
    while True:
        # 输出高电平并保持高电平对应的时间
        GPIO.output(PWM, GPIO.HIGH)
        time.sleep(period_h)
        # 输出低电平并保持低电平对应的时间
        GPIO.output(PWM, GPIO.LOW)
        time.sleep(period_l)
# 捕获键盘中断（Ctrl+C）信号
except KeyboardInterrupt:
    pass
# 清理GPIO设置，释放资源
GPIO.cleanup()